/** @todo 暂时不作检查 */
export const getTreeParentIds = (
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  tree: any[],
  nodeId: string,
  config?: {
    children: string;
    id: string;
  },
) => {
  const { children = 'children', id = 'key' } = config || {};

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const toFlatArray = (tree: any[], parentId?: string) => {
    return tree.reduce((t, _) => {
      const child = _[children];
      return [
        ...t,
        parentId ? { ..._, parentId } : _,
        ...(child && child.length ? toFlatArray(child, _[id]) : []),
      ];
    }, []);
  };

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const getIds = (flatArray: Array<any>) => {
    let ids = [nodeId];
    let child = flatArray.find((_) => _[id] === nodeId);
    while (child && child.parentId) {
      ids = [child.parentId, ...ids];

      // eslint-disable-next-line @typescript-eslint/no-loop-func
      child = flatArray.find((_) => _[id] === child.parentId);
    }
    return ids;
  };
  return getIds(toFlatArray(tree));
};

const childNodesDeep = (nodes, arr) => {
  if (nodes)
    nodes.forEach((ele) => {
      arr.push(ele.key);
      if (ele.children) {
        childNodesDeep(ele.children, arr);
      }
    });
};

export const getTreeChildIds = (nodes, key: string, arr?: string[]) => {
  for (const el of nodes) {
    if (el.key === key) {
      (arr || []).push(el.key);
      if (el.children) {
        childNodesDeep(el.children, arr);
      }
    } else if (el.children) {
      getTreeChildIds(el.children, key, arr);
    }
  }
  return arr;
};

type IDiffType = 'add' | 'delete';

/**
 *
 * @param oldValue string[]
 * @param newValue string[]
 * @returns
 */
export const findArrDiff = (
  oldValue: string[],
  newValue: string[],
): {
  type: 'add' | 'delete';
  diff: string[];
} => {
  let set: Set<string>;
  let diff;
  let type: IDiffType;
  if (newValue?.length > oldValue?.length) {
    type = 'add';
    set = new Set(oldValue);
    diff = newValue.filter((v) => !set.has(v));
  } else {
    type = 'delete';
    set = new Set(newValue);
    diff = oldValue.filter((v) => !set.has(v));
  }
  return { diff, type };
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function flatTree(list: any[], result: any[] = []): any[] {
  list.forEach((node) => {
    result.push({ ...node });
    if (node.children) flatTree(node.children, result);
  });
  return result;
}
